home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
__fstat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-27
|
9KB
|
270 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
*
* __fstat.c,v
* Revision 1.1.1.1 1994/04/04 04:30:08 amiga
* Initial CVS check in.
*
* Revision 1.2 1993/11/05 21:49:59 mw
* "grp/oth-perms,
*
* Revision 1.1 1992/05/14 19:55:40 mwild
* Initial revision
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
#if __GNUC__ != 2
#define alloca __builtin_alloca
#endif
#ifndef ACTION_EXAMINE_FH
#define ACTION_EXAMINE_FH 1034
#endif
#ifndef ST_LINKDIR
#define ST_ROOT 1
#define ST_USERDIR 2
#define ST_SOFTLINK 3 /* looks like dir, but may point to a file! */
#define ST_LINKDIR 4 /* hard link to dir */
#define ST_FILE -3 /* must be negative for FIB! */
#define ST_LINKFILE -4 /* hard link to file */
#define ST_PIPEFILE -5 /* for pipes that support ExamineFH */
#endif
extern void *alloca ();
/************************************************************************/
/* */
/* fstat() function. */
/* */
/************************************************************************/
int
__fstat(struct file *f)
{
long len, pos;
struct FileInfoBlock *fib;
struct InfoData *info;
int omask;
omask = syscall (SYS_sigsetmask, ~0);
__get_file (f);
/* take special care of NIL:, /dev/null and friends ;-) */
if (HANDLER_NIL(f))
{
f->f_stb.st_mode = S_IFCHR | 0777;
f->f_stb.st_nlink = 1;
f->f_stb.st_blksize = ix.ix_fs_buf_factor * 512;
f->f_stb.st_blocks = 0;
goto end;
}
info = alloca (sizeof (*info) + 2);
info = LONG_ALIGN (info);
fib = alloca (sizeof (*fib) + 2);
fib = LONG_ALIGN (fib);
__wait_packet (&f->f_sp);
/* reset the error field */
LastError (f) = 0;
/* we now have two possibilities.. either the filesystem understands the
* new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
/* SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, CTOBPTR(f->f_fh), CTOBPTR(fib));*/
SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
__wait_packet (&f->f_sp);
if (LastResult(f))
{
int mode;
f->f_stb.st_nlink = 1; /* always one link entry per file, unless... */
f->f_stb.st_amode = fib->fib_Protection;
mode = 0;
if (!(fib->fib_Protection & FIBF_EXECUTE))
mode |= S_IXUSR;
else if (fib->fib_Protection & FIBF_SCRIPT)
mode |= S_IXUSR;
if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
mode |= S_IWUSR;
if (!(fib->fib_Protection & FIBF_READ))
mode |= S_IRUSR;
#ifdef FIBF_GRP_EXECUTE
/* FIBF_GRP_EXECUTE requires at least OS3 headers */
if (fib->fib_Protection & FIBF_GRP_EXECUTE)
mode |= S_IXGRP;
if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
mode |= S_IWGRP;
if (fib->fib_Protection & FIBF_GRP_READ)
mode |= S_IRGRP;
if (fib->fib_Protection & FIBF_OTR_EXECUTE)
mode |= S_IXOTH;
if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
mode |= S_IWOTH;
if (fib->fib_Protection & FIBF_OTR_READ)
mode |= S_IROTH;
#endif
switch (fib->fib_DirEntryType)
{
case ST_LINKDIR:
f->f_stb.st_nlink++; /* we never get more than a link count of two.. */
case ST_ROOT:
case ST_USERDIR:
mode |= S_IFDIR;
break;
/* at the moment, we NEVER get this entry, since we can't get a lock
* on a symlink */
case ST_SOFTLINK:
mode |= S_IFLNK;
break;
case ST_PIPEFILE:
/* don't use S_IFIFO, we don't have a mkfifo() call ! */
mode |= S_IFCHR;
break;
case ST_LINKFILE:
f->f_stb.st_nlink ++;
case ST_FILE:
default:
mode |= S_IFREG;
}
/* ARGLLLLL !!!
Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
don't know yet about ST_PIPEFILE. So console windows claim they're
plain files... Until this problem is fixed in a majority of
handlers, do an explicit SEEK here to find those fakers.. */
LastError(f) = 0;
SendPacket3(f,__rwport,ACTION_SEEK,f->f_fh->fh_Arg1,0,OFFSET_CURRENT);
__wait_packet (&f->f_sp);
if (LastError (f))
mode = (mode & ~S_IFREG) | S_IFCHR;
f->f_stb.st_mode = mode;
/* support for annotated attributes (cool name ;-)) */
if (! strncmp (fib->fib_Comment, "!SP!", 4))
{
int sp_mode, sp_addr;
if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
f->f_stb.st_mode = sp_mode;
}
/* some kind of a default-size for directories... */
f->f_stb.st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024;
f->f_stb.st_handler = (long)f->f_fh->fh_Type;
f->f_stb.st_dev = (dev_t)f->f_stb.st_handler; /* trunc to 16 bit */
f->f_stb.st_ino = fib->fib_DiskKey;
f->f_stb.st_atime =
f->f_stb.st_ctime =
f->f_stb.st_mtime = (8*365+2)*24*3600 + /* offset to unix-timesystem */
fib->fib_Date.ds_Days * 24 * 60 * 60 +
fib->fib_Date.ds_Minute * 60 +
fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
/* in a try to count the blocks used for filemanagement, we add one for
* the fileheader. Note, that this is wrong for large files, where there
* are some extension-blocks as well */
f->f_stb.st_blocks = fib->fib_NumBlocks + 1;
}
else
{
/* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
/* seek to EOF */
SendPacket3 (f, __rwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
__wait_packet (&f->f_sp);
pos = LastResult (f);
if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
{
SendPacket3 (f, __rwport,ACTION_SEEK, f->f_fh->fh_Arg1,
pos, OFFSET_BEGINNING);
__wait_packet (&f->f_sp);
len = LastError (f) ? -1 : LastResult (f);
}
else
len = 0;
bzero (&f->f_stb, sizeof(struct stat));
f->f_stb.st_mode = ((len >= 0 &&
/* !IsInteractive(CTOBPTR(f->f_fh)) */! f->f_fh->fh_Port)
? S_IFREG : S_IFCHR) | 0777;
f->f_stb.st_handler = (long)f->f_fh->fh_Type;
/* the following is a limited try to support programs, that assume that
* st_dev is always valid */
f->f_stb.st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
/* yet another kludge.. if we call this with different descriptors, we
* should get different inode numbers.. grmpf.. */
f->f_stb.st_ino = (ino_t)~(long)(f->f_fh);
f->f_stb.st_nlink = 1; /* for now no problem.. 2.0... */
/* len could be -1, if the device doesn't allow seeking.. */
f->f_stb.st_size = len >= 0 ? len : 0;
f->f_stb.st_atime =
f->f_stb.st_mtime =
f->f_stb.st_ctime = syscall (SYS_time, 0);
}
/* try to find out block size of device, hey postman, it's packet-time
* again:-)) */
/* make sure, the packet is not in use anymore */
__wait_packet(&f->f_sp);
/* clear the info-structure. Since this packet is used by the console
* handler to transmit the window pointer, it actually answers the
* request, but doesn't set the not used fields to 0.. this gives HUGE
* block lengths :-)) */
bzero (info, sizeof(*info));
SendPacket1(f,__rwport,ACTION_DISK_INFO,CTOBPTR(info));
__wait_packet(&f->f_sp);
f->f_stb.st_blksize = 0;
if (LastResult (f) && info->id_BytesPerBlock)
{
f->f_stb.st_blksize = info->id_BytesPerBlock;
if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(f->f_stb.st_mode))
f->f_stb.st_blksize *= ix.ix_fs_buf_factor;
if (! f->f_stb.st_blocks)
f->f_stb.st_blocks = ((f->f_stb.st_size + info->id_BytesPerBlock - 1)
/ info->id_BytesPerBlock);
}
if (! f->f_stb.st_blksize)
{
f->f_stb.st_blksize = 512;
f->f_stb.st_blocks = (f->f_stb.st_size + 511) >> 9;
}
end:
/* reset error of packet. write() would fail if not */
LastResult(f) = 0;
__release_file (f);
syscall (SYS_sigsetmask, omask);
return 0;
}